package com.ruoyi.religion.sdk;

import com.ruoyi.religion.domain.*;
import com.ruoyi.religion.lib.NetDEVSDKLib;
import com.ruoyi.religion.mapper.*;
import com.ruoyi.religion.tools.DateUtils;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.swing.table.DefaultTableModel;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.ruoyi.religion.lib.NetDEVSDKLib.NETDEV_LOGIN_PROTO_E.NETDEV_LOGIN_PROTO_ONVIF;
import static com.sun.jna.Pointer.NULL;

@Service
public class MyAsync {

    @Autowired
    ReAlarmRecordMapper alarmService;

    @Autowired
    RePlaceMapper placeService;

    @Autowired
    ReInfoMachineMapper infoMachineService;

    @Autowired
    ReMachineMapper machineService;

    @Autowired
    ReCountPersonMapper countMapper;

    @Value("${file.path}")
    String path;

    public static NetDEVSDKLib netdevsdk = NetDEVSDKLib.NETDEVSDK_INSTANCE;

    public static Pointer lpUserID = null;

    static Log log = LogFactory.getLog(NetDemo.class);

    @Async
    void async(){
        //设置连接时间
        NetDEVSDKLib.NETDEV_REV_TIMEOUT_S stRevTimeout = new NetDEVSDKLib.NETDEV_REV_TIMEOUT_S();
        stRevTimeout.dwRevTimeOut = 5;
        stRevTimeout.dwFileReportTimeOut = 30;
        netdevsdk.NETDEV_SetRevTimeOut(stRevTimeout);

        //硬件设备列表
        List<ReInfoMachine> infoMachineList = infoMachineService.selectReInfoMachineList(new ReInfoMachine());

        for (ReInfoMachine reInfoMachine : infoMachineList) {

            try {


                NetDEVSDKLib.NETDEV_DEVICE_LOGIN_INFO_S stDevLoginInfo = new NetDEVSDKLib.NETDEV_DEVICE_LOGIN_INFO_S();

                //单个硬件设备的信息
                ReMachine reMachine = machineService.selectReMachineById2(Long.valueOf(reInfoMachine.getMachineId()));
                //设备对应区域
                RePlace rePlace = placeService.selectRePlaceById(reMachine.getPlaceId());

                //设置登录参数
                String strUserName = reInfoMachine.getUser();
                String strPassword = reInfoMachine.getPassword();
                String strPort = reInfoMachine.getPort();
                String strIp = reInfoMachine.getIp();

                System.arraycopy(strUserName.getBytes(), 0, stDevLoginInfo.szUserName, 0, strUserName.getBytes().length);
                System.arraycopy(strPassword.getBytes(), 0, stDevLoginInfo.szPassword, 0, strPassword.getBytes().length);
                System.arraycopy(strIp.getBytes(), 0, stDevLoginInfo.szIPAddr, 0, strIp.getBytes().length);
                stDevLoginInfo.dwPort = Integer.parseInt(strPort);
                stDevLoginInfo.dwDeviceType = 0;
                stDevLoginInfo.dwLoginProto = NETDEV_LOGIN_PROTO_ONVIF;

                //登陆成功.失败的操作记录
                NetDEVSDKLib.NETDEV_SELOG_INFO_S stSELogInfo = new NetDEVSDKLib.NETDEV_SELOG_INFO_S();
                lpUserID = netdevsdk.NETDEV_Login_V30(stDevLoginInfo, stSELogInfo);
                if (NULL == lpUserID) {

                    reMachine.setOnlineStatus("0");
                    reMachine.setUpdateTime(DateUtils.getNowDate());
                    machineService.updateReMachineByMac(reMachine);

                    log.info( rePlace.getName() + "设备状态已更新:离线" );
                    log.info( rePlace.getName() + "登录失败" );

                    netdevsdk.NETDEV_Logout(lpUserID);

                    log.info( rePlace.getName() + "已注销" );

                    continue;

                }else{

                    reMachine.setOnlineStatus("1");
                    reMachine.setUpdateTime(DateUtils.getNowDate());
                    machineService.updateReMachineByMac(reMachine);
                    log.info( rePlace.getName() + "设备状态已更新:在线" );

                }

                //获取通道状态
                int nMaxChlCount = 256;
                IntByReference dwChlCount = new IntByReference(nMaxChlCount);
                NetDEVSDKLib.NETDEV_VIDEO_CHL_DETAIL_INFO_EX_S[] stVideoChlList = (NetDEVSDKLib.NETDEV_VIDEO_CHL_DETAIL_INFO_EX_S[]) new NetDEVSDKLib.NETDEV_VIDEO_CHL_DETAIL_INFO_EX_S().toArray(nMaxChlCount);
                boolean bRet = netdevsdk.NETDEV_QueryVideoChlDetailListEx(lpUserID, dwChlCount, stVideoChlList);

                List<Integer> list = new ArrayList<>();
                if (bRet) {
                    for (int i = 0; i < dwChlCount.getValue(); i++) {
                        if (Common.DevideStatusToString(stVideoChlList[i].enStatus).equals("online")){
                            list.add(stVideoChlList[i].dwChannelID);
                        }
                    }
                }

                int in = 0;
                int out = 0;
                for (Integer integer : list) {

                    NetDEVSDKLib.NETDEV_MULTI_TRAFFIC_STATISTICS_COND_S stStatisticCond = new NetDEVSDKLib.NETDEV_MULTI_TRAFFIC_STATISTICS_COND_S();
                    stStatisticCond.stChannelIDs = new NetDEVSDKLib.NETDEV_OPERATE_LIST_S();
                    stStatisticCond.stChannelIDs.pstOperateInfo = new Memory(4);
                    stStatisticCond.stChannelIDs.pstOperateInfo.setInt(0, integer);
                    stStatisticCond.stChannelIDs.dwSize = 1;

                    stStatisticCond.udwFormType = NetDEVSDKLib.NETDEV_TRAFFIC_STATIC_FORM_TYPE_E.NETDEV_TRAFFIC_STAT_FORM_BY_DAY;
                    stStatisticCond.udwStatisticsType = NetDEVSDKLib.NETDEV_TRAFFIC_STATISTICS_TYPE_E.NETDEV_TRAFFIC_STATISTICS_TYPE_ALL;

                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.HOUR_OF_DAY, 0);
                    calendar.set(Calendar.HOUR, 0);
                    calendar.set(Calendar.MINUTE, 0);
                    calendar.set(Calendar.SECOND, 0);

                    long now = System.currentTimeMillis() / 1000l;
                    long daySecond = 60 * 60 * 24;
                    stStatisticCond.tBeginTime = now - (now + 8 * 3600) % daySecond;
                    stStatisticCond.tEndTime = stStatisticCond.tBeginTime + 24 * 3600;

                    IntByReference udwSearchID = new IntByReference();

                    // 开启查询
                    netdevsdk.NETDEV_StartMultiTrafficStatistic(lpUserID, stStatisticCond, udwSearchID);

                    // 获取列表
                    IntByReference dwProgress = new IntByReference();
                    try {
                        do {
                            netdevsdk.NETDEV_GetTrafficStatisticProgress(lpUserID, udwSearchID.getValue(), dwProgress);
                        } while (dwProgress.getValue() != 100);
                    } catch (Exception ignored) {
                    }

                    // 查询信息列表
                    Pointer lpStaticHandle = netdevsdk.NETDEV_FindTrafficStatisticInfoList(lpUserID, udwSearchID.getValue());

                    NetDEVSDKLib.NETDEV_TRAFFIC_STATISTICS_INFO_S stStatisticInfo = new NetDEVSDKLib.NETDEV_TRAFFIC_STATISTICS_INFO_S();
                    netdevsdk.NETDEV_FindNextTrafficStatisticInfo(lpStaticHandle, stStatisticInfo);

                    in = in + stStatisticInfo.audwEnterCount[0];
                    out = out + stStatisticInfo.audwExitCount[0];

                    netdevsdk.NETDEV_FindCloseTrafficStatisticInfo(lpStaticHandle);

                    netdevsdk.NETDEV_StopTrafficStatistic(lpUserID, udwSearchID.getValue());

                }

                String num = rePlace.getSiteCapacity();
                if (num == null) {
                    num = "1";
                }

                //超过人数添加记录
                int temp = Math.abs( in - out );
                String strandPerson = rePlace.getStrandPerson();
                if (strandPerson == null || strandPerson.equals("")){
                    strandPerson = "0";
                }

                if ( temp > Integer.parseInt(num) && temp != Integer.parseInt(strandPerson) ){
                    ReAlarmRecord reAlarmRecord = new ReAlarmRecord();//设备告警表
                    reAlarmRecord.setSitePeopleNumber(temp+"");
                    reAlarmRecord.setSiteCapacity(num);
                    reAlarmRecord.setType("4");
                    reAlarmRecord.setMachineId(Long.valueOf(reInfoMachine.getMachineId()));
                    reAlarmRecord.setPersonCardNumber(reMachine.getCode());
                    reAlarmRecord.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) );
                    reAlarmRecord.setDelFlag("0");
                    reAlarmRecord.setCreateTime(DateUtils.getNowDate());
                    alarmService.insertReAlarmRecord(reAlarmRecord);
                }


                // 2023.03.09新增
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
                Date date = new Date();
                String day = dateFormat.format(new Date());

                ReCountPerson countPerson = new ReCountPerson();
                countPerson.setPlaceId(reInfoMachine.getPlaceId());
                countPerson.setDay(day);
                countPerson.setUpdateTime(date);

                String uri = path + day + reInfoMachine.getPlaceId();

                List<ReCountPerson> countPersonList = countMapper.selectReCountPersonList(countPerson);

                if ( countPersonList.size() == 0 ){

                    countPerson.setCount(temp+"");
                    countPerson.setYear(day.substring(0,4));
                    countPerson.setMonth(day.substring(0,6));
                    int weekForYear = getWeekForYear(date);
                    countPerson.setWeek(weekForYear+"");
                    countPerson.setImg( "/countImg/" + day + reInfoMachine.getPlaceId() + ".jpg" );

                    countMapper.insertReCountPerson(countPerson);

                    netdevsdk.NETDEV_CaptureNoPreview(lpUserID,
                            1,
                            NetDEVSDKLib.NETDEV_LIVE_STREAM_INDEX_E.NETDEV_LIVE_STREAM_INDEX_MAIN,
                            uri,
                            NetDEVSDKLib.NETDEV_PICTURE_FORMAT_E.NETDEV_PICTURE_JPG
                    );

                }else {

                    ReCountPerson reCountPerson = countPersonList.get(0);

                    int i = netdevsdk.NETDEV_GetLastError();
                    log.info( "i = " + i);

                    if ( temp > Integer.parseInt(reCountPerson.getCount()) ){
                        countPerson.setCount(temp+"");
                        countMapper.updateCount(countPerson);

                        netdevsdk.NETDEV_CaptureNoPreview(lpUserID,
                                1,
                                NetDEVSDKLib.NETDEV_LIVE_STREAM_INDEX_E.NETDEV_LIVE_STREAM_INDEX_MAIN,
                                uri,
                                NetDEVSDKLib.NETDEV_PICTURE_FORMAT_E.NETDEV_PICTURE_JPG
                        );
                    }

                }



                //注销用户
                netdevsdk.NETDEV_Logout(lpUserID);

                log.info( rePlace.getName()  + ":  进入人数:" + in + ",离开人数:" + out );

            } catch (Exception e) {
                log.info("错误信息 : " + e);
            }

        }
    }

    public static int getWeekForYear(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setMinimalDaysInFirstWeek(1);
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

}
